package essential.ch3;

/**
 * @Date 2021/10/23
 * @Created by Jonathan
 * todo 所谓常量表达式，就是编译的时候可以确定其值的String类型的表达式。
 * 总结：
 * (1)String类维护一块特殊的区域，称为常量池。因为String对象是不可改变的，因此没有必要创建两个相同的String对象。
 * 只需将String对象加入常量池，在需要的时候取出，这样即可实现String对象的共享。
 * (2)在程序中出现String编译时常量（String字面常量与String常量表达式）时，【会自动调用intern方法】，
 * 如果常量池中含有相等的String对象，则直接返回常量池中的对象，否则将对象加入常量池中并返回该对象。
 * (3)对于运行时创建的String对象（非String编译时常量），会分配到堆中，系统不会自动调用intern方法拘留该对象，
 * 不过我们依然可以自行调用该对象的intern方法对该对象进行拘留。
 */
public class StringTest3 {
    public static void main(String[] args) {
        String s1 = "black";
        String s2 = "board";
        /**
         * s3、s4、s5都是在运行期间才能确定所指的String对象地址，
         * 3个引用所指向的地址都是不同的
         */
        String s3 = s1 + s2;
        String s4 = "black" + s2;
        String s5 = s1 + "board";
        System.out.printf("s3==s4:%s\n", s3 == s4);
        System.out.printf("s3==s5:%s\n", s3 == s5);
        System.out.printf("s4==s5:%s\n", s4 == s5);
        /**
         * 3个引用调用intern方法，返回的String对象却是同一个对象（第13～18行），
         * 因为3个引用指向的String对象的字符序列是相等的，都为“blackboard”，
         * 当s3调用intern方法时，常量池中不存在“blackboard”，
         * 于是常量池加入该对象，并返回该对象
         */
        System.out.printf("s3.intern() == s4.intern():%s\n", s3.intern() == s4.intern());
        System.out.printf("s4.intern() == s3.intern():%s\n", s4.intern() == s3.intern());
        System.out.printf("s3.intern() == s5.intern():%s\n", s3.intern() == s5.intern());
        System.out.printf("s4.intern() == s5.intern():%s\n", s4.intern() == s5.intern());
        /**
         *s1与s2指向的String对象是字面常量，系统自动调用intern方法将对象加入常量池，
         * 因此这两个引用指向的String对象与调用intern方法返回的String对象是同一对象
         */
        System.out.printf("s1 == s1.intern():%s\n", s1 == s1.intern());
        System.out.printf("s2 == s2.intern():%s\n", s2 == s2.intern());
        /**
         * 加入常量池的对象就是s3所指向的对象
         */
        System.out.printf("s3 == s3.intern():%s\n", s3 == s3.intern());
        /**
         * 调用intern也是返回上面加入常量池的对象 s4/s5是分配到到堆空间的
         */
        System.out.printf("s4 == s4.intern():%s\n", s4 == s4.intern());
        System.out.printf("s5 == s5.intern():%s\n", s5 == s5.intern());
        // 扩展
        System.out.printf("扩展ret:%s\n", 3 + 4 + "5" == "3" + 4 + 5);
    }
}
